page.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import '@/app/(main)/paper/style.scss';
  2. import { TrendingUp, Target, TrendingDown, ListChecks } from 'lucide-react';
  3. import { fetchPaperTrackRecord } from '@/lib/api/paper';
  4. import { formatBpPercent, formatBpAbs, bpDirection } from '@/lib/utils/paper';
  5. type Props = {
  6. params: Promise<{ sid: string }>;
  7. };
  8. // 프로필 "모의투자 성적" 탭 (익명 허용 · SSR) — 누적수익률·승률·MDD·체결수
  9. export default async function UserProfilePaperPage({ params }: Props)
  10. {
  11. const { sid } = await params;
  12. const res = await fetchPaperTrackRecord(sid);
  13. const record = res.success ? res.data : null;
  14. if (!res.success) {
  15. return <div className='paper__error' role='alert'>모의투자 성적을 불러오지 못했습니다.</div>;
  16. }
  17. if (!record || !record.hasAccount) {
  18. return <div className='user-profile__empty'>아직 모의투자에 참여하지 않았습니다.</div>;
  19. }
  20. const returnDir = bpDirection(record.cumReturnBp);
  21. return (
  22. <section className='user-profile__stats' aria-label='모의투자 성적'>
  23. <div className='user-profile__stat'>
  24. <TrendingUp size={20} className='user-profile__stat-icon' strokeWidth={1.75} />
  25. <div className='user-profile__stat-body'>
  26. <span className='user-profile__stat-label'>누적 수익률</span>
  27. <span className={`user-profile__stat-value paper__value--${returnDir}`}>{formatBpPercent(record.cumReturnBp)}</span>
  28. </div>
  29. </div>
  30. <div className='user-profile__stat'>
  31. <Target size={20} className='user-profile__stat-icon' strokeWidth={1.75} />
  32. <div className='user-profile__stat-body'>
  33. <span className='user-profile__stat-label'>승률</span>
  34. <span className='user-profile__stat-value'>{formatBpAbs(record.winRateBp)}</span>
  35. </div>
  36. </div>
  37. <div className='user-profile__stat'>
  38. <TrendingDown size={20} className='user-profile__stat-icon' strokeWidth={1.75} />
  39. <div className='user-profile__stat-body'>
  40. <span className='user-profile__stat-label'>최대 낙폭 (MDD)</span>
  41. <span className='user-profile__stat-value paper__value--down'>{formatBpAbs(record.mddBp)}</span>
  42. </div>
  43. </div>
  44. <div className='user-profile__stat'>
  45. <ListChecks size={20} className='user-profile__stat-icon' strokeWidth={1.75} />
  46. <div className='user-profile__stat-body'>
  47. <span className='user-profile__stat-label'>체결 수</span>
  48. <span className='user-profile__stat-value'>{record.fillCount.toLocaleString()}</span>
  49. </div>
  50. </div>
  51. </section>
  52. );
  53. }